/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.service.paste;

import cn.ac.nercis.pes.common.constant.evaluation.EvaluationModule;
import cn.ac.nercis.pes.model.dto.common.DataCopy;
import cn.ac.nercis.pes.model.dto.common.DataPaste;
import cn.ac.nercis.pes.model.dto.common.Result;
import cn.ac.nercis.pes.model.dto.evaluation.analyze.ResultCorrectionDTO;
import cn.ac.nercis.pes.model.dto.evaluation.analyze.UnitEvaluationDTO;
import cn.ac.nercis.pes.model.dto.evaluation.analyze.UnitRiskAnalysisDTO;
import cn.ac.nercis.pes.model.dto.project.SystemProcessDTO;
import cn.ac.nercis.pes.service.evaluation.ResultCorrectionService;
import cn.ac.nercis.pes.service.evaluation.UnitEvaluationService;
import cn.ac.nercis.pes.service.evaluation.UnitRiskAnalysisService;
import cn.ac.nercis.pes.service.project.SystemProcessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;


/**
 * 分析与报告编制阶段相关数据粘贴服务类
 *
 * @author limy
 * @version 1.0.0
 */
@Slf4j
@Service
public record AnalyzePasteService(UnitEvaluationService unitEvaluationService,
                                  ResultCorrectionService resultCorrectionService,
                                  UnitRiskAnalysisService unitRiskAnalysisService,
                                  SystemProcessService systemProcessService) {

    @Autowired
    public AnalyzePasteService {
    }

    public Result<String> unitEvalDataPaste(DataPaste dataPaste, DataCopy dataCopy) {
        if (StringUtils.equals(dataCopy.getName(), dataPaste.getName())
                && StringUtils.equals(dataCopy.getData(), dataPaste.getData())
                && StringUtils.equals(dataCopy.getCopySystemId(), dataPaste.getSystemId())) {
            return Result.success();
        }
        var copyUnitEval = unitEvaluationService.findUnitEvaluationByLayerTarget(dataCopy.getCopySystemId(), dataCopy.getData());
        if (!copyUnitEval.isSuccess()) {
            return Result.failed("无复制的单元测评信息！");
        }
        var pasteUnitEval = unitEvaluationService.findUnitEvaluationByLayerTarget(dataPaste.getSystemId(), dataPaste.getData());
        if (!pasteUnitEval.isSuccess()) {
            return Result.failed(pasteUnitEval.getMsg());
        }
        return pasteUnitEvalData(copyUnitEval.getData(), pasteUnitEval.getData(), dataCopy, dataPaste);
    }


    private Result<String> pasteUnitEvalData(List<UnitEvaluationDTO> copyUnitEvaluations, List<UnitEvaluationDTO> pasteUnitEvaluations, DataCopy dataCopy, DataPaste dataPaste) {
        var modifyData = copyUnitEvaluations.stream()
                .map(cue -> {
                    var pueUnitEval = pasteUnitEvaluations.stream()
                            .filter(pue -> StringUtils.equals(cue.getUnitTargetName(), pue.getUnitTargetName()))
                            .findFirst()
                            .orElse(null);
                    if (Objects.nonNull(pueUnitEval)) {
                        pueUnitEval.setResultAnalysis(cue.getResultAnalysis());
                    }
                    return pueUnitEval;
                })
                .filter(Objects::nonNull)
                .toList();
        var result = unitEvaluationService.batchSaveUnitEvaluation(modifyData);
        if (result.isSuccess()) {
            pasteUnitEvalFinishState(dataCopy, dataPaste);
        }
        return result;
    }

    private void pasteUnitEvalFinishState(DataCopy dataCopy, DataPaste dataPaste) {
        var copyFinishState = systemProcessService.findUnitEvalProcess(dataCopy.getCopySystemId())
                .stream()
                .filter(ps -> StringUtils.equals(ps.getName(), dataCopy.getName()))
                .map(SystemProcessDTO::getFinishState)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(copyFinishState)) {
            return;
        }
        unitEvaluationService.setUnitEvalFinishState(dataPaste.getSystemId(), dataPaste.getData(), copyFinishState);
        EvaluationModule module = EvaluationModule.fromNameByUnitEval(dataCopy.getName());
        systemProcessService.setSystemProcess(dataPaste.getSystemId(), module, copyFinishState);
    }


    public Result<String> resultCorrectionDataPaste(DataPaste dataPaste, DataCopy dataCopy) {
        if (StringUtils.equals(dataPaste.getSystemId(), dataCopy.getCopySystemId())
                && StringUtils.equals(dataPaste.getName(), dataCopy.getName())) {
            return Result.success();
        }
        //获取列表信息
        var copyResultCorrections = this.resultCorrectionService.findResultCorrectionByLayerTarget(dataCopy.getCopySystemId(), dataCopy.getData(), false);
        if (!copyResultCorrections.isSuccess()) {
            return Result.failed("复制的整体测评层面指标下，无需要修正的测评记录信息！");
        }
        var pasteResultCorrections = this.resultCorrectionService.findResultCorrectionByLayerTarget(dataPaste.getSystemId(), dataPaste.getData(), false);
        if (!pasteResultCorrections.isSuccess()) {
            return Result.failed("粘贴的整体测评层面指标下，无需要修正的测评记录信息！");
        }
        //执行粘贴操作
        return pasteResultCorrection(copyResultCorrections.getData(), pasteResultCorrections.getData(), dataPaste, dataCopy);
    }

    private Result<String> pasteResultCorrection(List<ResultCorrectionDTO> copyResultCorrections, List<ResultCorrectionDTO> pasteResultCorrections,
                                                 DataPaste dataPaste, DataCopy dataCopy) {
        var modifyData = copyResultCorrections.stream()
                .map(crc -> pasteResultCorrection(crc, pasteResultCorrections))
                .filter(Objects::nonNull)
                .toList();
        var result = resultCorrectionService.batchSaveResultCorrection(modifyData);
        if (result.isSuccess()) {
            pasteResultCorrectionFinishState(dataCopy, dataPaste);
        }
        return result;
    }

    private ResultCorrectionDTO pasteResultCorrection(ResultCorrectionDTO copyResultCorrection, List<ResultCorrectionDTO> pasteResultCorrections) {
        var pasteResultCorrection = pasteResultCorrections.stream()
                .filter(prc -> StringUtils.equals(prc.getUnitTargetName(), copyResultCorrection.getUnitTargetName())
                        && StringUtils.equals(prc.getAssetName(), copyResultCorrection.getAssetName()))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(pasteResultCorrection) || StringUtils.isBlank(copyResultCorrection.getOffsetRecordId())) {
            return null;
        }
        var copyOffsetAsset = resultCorrectionService.getOffsetAssets(copyResultCorrection.getOffsetRecordId()).getData();
        if (Objects.isNull(copyOffsetAsset)) {
            return null;
        }
        var pasteOffsetAsset = resultCorrectionService.findOffsetAssets(pasteResultCorrection.getSystemId(), pasteResultCorrection.getAssetId(), pasteResultCorrection.getUnitTargetId())
                .stream()
                .filter(poa -> StringUtils.equals(poa.getLayerTargetName(), copyOffsetAsset.getLayerTargetName())
                        && StringUtils.equals(poa.getUnitTargetName(), copyOffsetAsset.getUnitTargetName())
                        && StringUtils.equals(poa.getAssetName(), copyOffsetAsset.getAssetName()))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(pasteOffsetAsset)) {
            return null;
        }
        pasteResultCorrection.setOffsetRecordId(pasteOffsetAsset.getRecordId());
        pasteResultCorrection.setOffsetAssetName(pasteOffsetAsset.getAssetName());
        resultCorrectionService.computerResultCorrection(pasteResultCorrection);
        pasteResultCorrection.setDesc(copyResultCorrection.getDesc());
        return pasteResultCorrection;
    }

    private void pasteResultCorrectionFinishState(DataCopy dataCopy, DataPaste dataPaste) {
        var copyFinishState = systemProcessService.findOverallEvalProcess(dataCopy.getCopySystemId())
                .stream()
                .filter(ps -> StringUtils.equals(ps.getName(), dataCopy.getName()))
                .map(SystemProcessDTO::getFinishState)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(copyFinishState)) {
            return;
        }
        resultCorrectionService.setFinishStateByLayerTarget(dataPaste.getSystemId(), dataPaste.getData(), copyFinishState);
        EvaluationModule module = EvaluationModule.fromNameByOverallEval(dataCopy.getName());
        systemProcessService.setSystemProcess(dataPaste.getSystemId(), module, copyFinishState);
    }

    public Result<String> riskAnalysisDataPaste(String currentSystemId, String currentLayerTargetId, DataCopy dataCopy) {
        if (StringUtils.equals(currentSystemId, dataCopy.getCopySystemId())
                && StringUtils.equals(currentLayerTargetId, dataCopy.getData())) {
            return Result.success();
        }
        //获取风险分析列表
        var pasteUnitRiskAnalysis = this.unitRiskAnalysisService.findRiskAnalysis(currentSystemId, currentLayerTargetId);
        var copyUnitRiskAnalysis = this.unitRiskAnalysisService.findRiskAnalysis(dataCopy.getCopySystemId(), dataCopy.getData());
        if (!copyUnitRiskAnalysis.isSuccess()) {
            return Result.failed("复制的风险分析层面指标下，无需测评记录信息！");
        }
        if (!pasteUnitRiskAnalysis.isSuccess()) {
            return Result.failed("粘贴的风险分析层面指标下，无需测评记录信息！");
        }
        return pasteRiskAnalysisData(copyUnitRiskAnalysis.getData(), pasteUnitRiskAnalysis.getData(), dataCopy, currentSystemId);
    }

    private Result<String> pasteRiskAnalysisData(List<UnitRiskAnalysisDTO> copyUnitRiskAnalysis, List<UnitRiskAnalysisDTO> pasteUnitRiskAnalysis,
                                                 DataCopy dataCopy, String pasteSystemId) {
        var modifyData = copyUnitRiskAnalysis.stream()
                .map(cra -> {
                    var pra = pasteUnitRiskAnalysis.stream()
                            .filter(pue -> StringUtils.equals(cra.getUnitTargetName(), pue.getUnitTargetName()))
                            .findFirst()
                            .orElse(null);
                    if (Objects.nonNull(pra)) {
                        pra.setProblem(cra.getProblem());
                        pra.setSuggest(cra.getSuggest());
                        pra.setAnalysis(cra.getAnalysis());
                        pra.setThreatCode(cra.getThreatCode());
                        pra.setRiskLevel(cra.getRiskLevel());
                    }
                    return pra;
                })
                .filter(Objects::nonNull)
                .toList();
        var result = unitRiskAnalysisService.batchSaveRiskAnalysis(modifyData);
        if (result.isSuccess()) {
            pasteRiskAnalysisFinishState(dataCopy, pasteSystemId);
        }
        return result;
    }

    private void pasteRiskAnalysisFinishState(DataCopy dataCopy, String pasteSystemId) {
        var copyFinishState = systemProcessService.findRiskAnalysisProcess(dataCopy.getCopySystemId())
                .stream()
                .filter(ps -> StringUtils.equals(ps.getName(), dataCopy.getName()))
                .map(SystemProcessDTO::getFinishState)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(copyFinishState)) {
            return;
        }
        EvaluationModule module = EvaluationModule.fromNameByRiskAnalysis(dataCopy.getName());
        systemProcessService.setSystemProcess(pasteSystemId, module, copyFinishState);
    }

    public Result<String> overallAppraiseDataPaste(String systemId, String layerTargetId, DataCopy dataCopy) {
        if (StringUtils.equals(systemId, dataCopy.getCopySystemId())
                && StringUtils.equals(layerTargetId, dataCopy.getData())) {
            return Result.success();
        }
        var pasteOverallEvaluationDTO = unitEvaluationService.getOverallEvaluation(systemId, layerTargetId);
        var copyOverallEvaluationDTO = unitEvaluationService.getOverallEvaluation(dataCopy.getCopySystemId(), dataCopy.getData());
        if (StringUtils.isBlank(copyOverallEvaluationDTO.getId())) {
            return Result.success();
        }
        pasteOverallEvaluationDTO.setContent(copyOverallEvaluationDTO.getContent());
        var opResult = unitEvaluationService.saveOverallEvaluation(pasteOverallEvaluationDTO);
        if (opResult.isSuccess()) {
            pasteOverallAppraiseFinishState(systemId, dataCopy);
            return Result.success();
        } else {
            return Result.failed("粘贴失败！");
        }
    }

    private void pasteOverallAppraiseFinishState(String systemId, DataCopy dataCopy) {
        var copyFinishState = systemProcessService.findOverallAppraiseProcess(dataCopy.getCopySystemId())
                .stream()
                .filter(ps -> StringUtils.equals(ps.getName(), dataCopy.getName()))
                .map(SystemProcessDTO::getFinishState)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(copyFinishState)) {
            return;
        }
        EvaluationModule module = EvaluationModule.fromNameByUnitEval(dataCopy.getName());
        systemProcessService.setSystemProcess(systemId, module, copyFinishState);
    }


}